/**********************************************************************
 *
 *  MODULE: MPADWIN.CPP
 *  AUTHOR: BRIAN M. WORKMAN
 *  START DATE: November 21, 2005, 5:49:52 PM
 *
 **********************************************************************/

#include "../G/g.h"
#include "mpadwin.h"
#include "about_me.h"
#include <qdebug.h>

MPadWin::MPadWin(QWidget *parent, Qt::WFlags f)
    : QMainWindow(parent, f) {

    m_initializing = true;
    m_opening = false;

    QFrame *central = new QFrame(this);    
    setCentralWidget(central);
    QVBoxLayout *v = new QVBoxLayout(central);
    central->setLayout(v);
    v->setSpacing(0);
    v->setMargin(0);

    tabs = new QTabWidget(central);
    v->addWidget(tabs);

    newTabButton = new QToolButton(tabs);
    newTabButton->setIcon(QIcon(":/tab_new"));
    newTabButton->setAutoRaise(true);

    removeTabButton = new QToolButton(tabs);
    removeTabButton->setIcon(QIcon(":/tab_remove"));
    removeTabButton->setAutoRaise(true);

    tabs->setCornerWidget(newTabButton, Qt::TopLeftCorner);
    tabs->setCornerWidget(removeTabButton, Qt::TopRightCorner);
    
    createActions();
    createMenus();
    createToolBars();
    createStatusBar();
    createWhatsThis();
    readSettings();

    move(m_pos);
    resize(m_size);
    tabs->show();
    newFile();
    m_closing = false;
    setMudFriendly(m_mudfriendly);
#ifndef Q_OS_X11
    if(m_maximized) setWindowState(Qt::WindowMaximized);
#endif
    toggleToolbarsAct->setChecked(m_toolbars);
    showHideToolbars();
    setLastPath(m_lastpath);
    m_initializing = false;
    QStringList args = qApp->arguments();
    if(args.count() > 1) {
        openFiles(args.mid(1,args.count()-1));
    }
    edLeft->setValue(m_indent);
    edRight->setValue(m_wrap);
    chkPreserveDot->setChecked(m_dot);
    actViewLines->setChecked(m_lines);
    updateDisplays();
    m_case = false;
    m_back = false;
    m_word = true;
    replace = 0;
    m_reload_timer = new QTimer(this);
    m_reload_timer->start(RELOAD_TIMER);
    fbar = new FindBar(central);
    v->addWidget(fbar);
    SHOWN = false;
    setupConnections();
}

void MPadWin::setupConnections() {
    connect(tabs, SIGNAL(currentChanged(int)), this, SLOT(switchDocument(int)));
    connect(this, SIGNAL(dataSaved(GNumberedEdit*)), 
        this, SLOT(updateStatus(GNumberedEdit*)));
    connect(m_reload_timer, SIGNAL(timeout()), this, 
        SLOT(checkDocumentChanges()));
    connect(fbar, SIGNAL(newSearchText(QString,bool,bool)), 
        this, SLOT(doFindB(QString,bool,bool)));
    connect(fbar, SIGNAL(findBarHidden(bool)), this, SLOT(findBarHidden(bool)));
    connect(this, SIGNAL(textFound(bool)), fbar, SLOT(textFound(bool)));
    connect(fbar, SIGNAL(requestFindNext(bool)), this, 
        SLOT(slotRequestFindNext(bool))); 
    connect(fbar, SIGNAL(requestFindPrevious(bool)), this, 
        SLOT(slotRequestFindPrevious(bool))); 
    connect(fonts, SIGNAL(currentFontChanged(QFont)),
        this, SLOT(fontUpdate(QFont)));
    connect(fontSize, SIGNAL(valueChanged(int)),
        this, SLOT(fontUpdateSize(int)));
}

void MPadWin::checkDocumentChanges() {
    if(qApp->activeModalWidget()) {
        return ;
    }
    QList<GNumberedEdit*> d = docs.keys();
    for(int i = 0; i < d.count(); i++) {
        m_reload_timer->stop();
        GNumberedEdit *v = d[i];
        if(docs[v].full_file_name.isEmpty()) continue;
        if(QFileInfo(docs[v].full_file_name).lastModified() > 
            docs[v].last_modified.addMSecs(1)) {
            tabs->setCurrentIndex(tabs->indexOf(v));
            if(QMessageBox::question(this, "MUDpad",
                QString(tr("<p>The document \'<strong>%1</strong>\' "
                "has recently changed outside of MUDpad. If you save "
                "now without reloading it then those changes will be "
                "lost.</p><p>Reloading the file will cause any changes "
                "you have made inside MUDpad to be lost.</p><p>Would you "
                "like to reload the file from disk?</p>"))
                .arg(QDir::convertSeparators(docs[v].full_file_name)),
                QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
                doReload(v);
            } else {
                if(QMessageBox::question(this, "MUDpad",
                    tr("<p>You have chosen not to reload the file. Would "
                    "you prefer to overwrite the file on disk with the "
                    "copy you have open presently?</p>"), 
                    QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
                    saveDocument(v);
                } else {
                    QMessageBox::warning(this, "MUDpad",
                        tr("<p>You will not be warned again unless the file "
                        "is modified externally before you save your "
                        "changes.</p>"));
                    docs[v].last_modified = QDateTime::currentDateTime();
                }
            }
        }
    }
    m_reload_timer->start(RELOAD_TIMER);
}

void MPadWin::closeEvent(QCloseEvent *event)
{
    bool success = true;
    m_closing = true;
    for(int i = tabs->count()-1; i >= 0 ; i--) {
      if(!closeFile()) {
        success = false;
        break;
      }
    }
    switch(success) {
        case true:
            writeSettings();
            event->accept();
            QMainWindow::closeEvent(event);
            break;
        case false:
            m_closing = false;
            event->ignore();
            break;
    }
}

bool MPadWin::doCloseAll () {
    int i = tabs->count();
    bool success = true;
    while(--i >= 0 && (success = 
        closeFile(qobject_cast<GNumberedEdit*>(tabs->widget(i))))) 
        qApp->processEvents();
    return success;
}

void MPadWin::assignConnections(GNumberedEdit *newview) {
    connect (newview, SIGNAL(textChanged()), this, SLOT(updateStatus()));
    connect (newview->edit(), SIGNAL(copyAvailable(bool)), this, 
        SLOT(enableCopy(bool)));
    connect (newview->edit(), SIGNAL(undoAvailable(bool)), this, 
        SLOT(enableUndo(bool)));
    connect (newview->edit(), SIGNAL(redoAvailable(bool)), this, 
        SLOT(enableRedo(bool)));
}

void MPadWin::initNewView(GNumberedEdit *newview) {
    newview->doc()->setModified(false);
    newview->edit()->setFocus();
    updateDisplay(newview);
    DocProps d;
    d.new_data = false;
    d.path = QString::null;
    d.file_name = QString::null;
    d.full_file_name = QString::null;
    d.copy_available = false;
    d.undo_available = false;
    d.redo_available = false;
    d.last_modified = QDateTime::currentDateTime();
    docs.insert(newview, d);
}

void MPadWin::newFile() {
    GNumberedEdit *v;
    tabs->addTab(v = new GNumberedEdit(tabs), QIcon(":/file_icon"), QString());
    tabs->setCurrentIndex(tabs->indexOf(v));
    assignConnections(v);
    initNewView(v);
    updateStatus(v);
}

QString MPadWin::title(GNumberedEdit *v) {
    QString t;
    return (t = docs[v].file_name).isNull() ? "Untitled" : t;
}

void MPadWin::open() {
    QStringList fileNames = 
        QFileDialog::getOpenFileNames(this, tr("Open File"), lastPath(), 
        FILE_ASSOC);
    if (!fileNames.isEmpty()) {
        openFiles(fileNames);
    }
    curDoc()->setFocus();
    return ;
}

bool MPadWin::loadFile(GNumberedEdit *v, QString fileName) {
    if(!v) {
        QMessageBox::critical(this, "MUDpad", tr("There was a problem loading "
        "a file."));
        return false ;
    }
    if(fileName.isEmpty()) {
        QMessageBox::critical(this, "MUDpad", tr("There was a problem loading "
        "a file."));
        return false;
    }
    m_opening = true;
    QFile file(fileName);
    if (!file.open(QFile::ReadOnly | QFile::Text)) {
        QMessageBox::warning(this, tr("MUDpad"),
            tr("Cannot read file %1:\n%2.").arg(fileName)
            .arg(file.errorString()));
        return false;
    }
    QTextStream in(&file);
    QApplication::setOverrideCursor(Qt::WaitCursor);
    QApplication::restoreOverrideCursor();
    QString buff = in.readAll();
    QString fill;
    fill.fill(QChar(32), 4);
    if(buff.indexOf(QChar(9)) > -1) {
        buff.replace(QChar(9), fill);
        QMessageBox::warning(this, tr("Tab Warning"),
            QString(tr("<p>The file <strong>%1</strong> contains TAB "
            "characters. As MUDs do not use this character, it has "
            "been replaced by 4 spaces at every occurrence.</p><p>Saving "
            "this file will cause the tabs to be over written with these "
            "spaces instead of the tabs.</p>")).arg(fileName)); 
    }        
    v->edit()->setText(buff);    
    m_opening = false;
    return true;
}

void MPadWin::openFiles(QStringList fileNames) {
    GNumberedEdit *v;
    QListIterator<QString> f(fileNames);
    while (f.hasNext()) {
        bool found = false;
        QString fileName(f.next());
        QListIterator<GNumberedEdit*> g(docs.keys());
        while(g.hasNext()) {
            GNumberedEdit *tmp = g.next();
            DocProps p = docs[tmp];
            if(QString("%1/%2").arg(p.path).arg(p.file_name) == fileName) {
                tabs->setCurrentIndex(tabs->indexOf(tmp));
                found = true;
                continue;
            }
        }
        if(found) continue;
        if(tabs->count() == 1 && 
            !(qobject_cast<GNumberedEdit*>(tabs->widget(0))->edit()->dirty()) && 
           docs[qobject_cast<GNumberedEdit*>(tabs->widget(0))]
           .file_name.isEmpty()) {
            v = qobject_cast<GNumberedEdit*>(tabs->widget(0));
            docs.remove(v);
        } else {
            tabs->addTab(v = new GNumberedEdit(tabs), 
                QIcon(":/file_icon"), QString());
        }
        tabs->setTabText(tabs->indexOf(v), title(v));

        QString str = fileName.section('/', -1);

        initNewView(v);        
        if(!loadFile(v, fileName)) {
            delete(v);
            continue;
        }
        docs[v].path = strippedPath(fileName);
        docs[v].file_name = strippedName(fileName);
        docs[v].full_file_name = fileName;
        docs[v].last_modified = QFileInfo(fileName).lastModified();
        setLastPath(docs[v].path);
        updateStatus(v);
        v->edit()->setMudFriendly(m_mudfriendly);
        assignConnections(v);
        v->edit()->setWrapColumn(m_wrap);
        v->edit()->setTextIndent(m_indent);
        tabs->setCurrentIndex(tabs->indexOf(v));
        qApp->processEvents();
    }
}

void MPadWin::save() {
    saveDocument(curTab());
}

void MPadWin::about() {
    AboutDialog aboutMe(this);
    aboutMe.exec();
}

void MPadWin::createActions() {
    newAct = new QAction(QIcon(":/new"), tr("&New"), this);
    newAct->setShortcut(tr("Ctrl+N"));
    newAct->setStatusTip(tr("Create a new file."));
    connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));

    newTabAct = new QAction(QIcon(":/newtab"), tr("&New"), this);
    newTabAct->setStatusTip(tr("Create a new file."));
    connect(newTabAct, SIGNAL(triggered()), this, SLOT(newFile()));
    newTabButton->setDefaultAction(newTabAct);

    removeTabAct = new QAction(QIcon(":/deltab"), tr("&Close"), this);
    removeTabAct->setStatusTip(tr("Close document."));
    connect(removeTabAct, SIGNAL(triggered()), this, SLOT(closeFile()));
    removeTabButton->setDefaultAction(removeTabAct);

    openAct = new QAction(QIcon(":/open"), tr("&Open..."), this);
    openAct->setShortcut(tr("Ctrl+O"));
    openAct->setStatusTip(tr("Open an existing file."));
    connect(openAct, SIGNAL(triggered()), this, SLOT(open()));

    saveAct = new QAction(QIcon(":/save"), tr("&Save"), this);
    saveAct->setShortcut(tr("Ctrl+S"));
    saveAct->setStatusTip(tr("Save the document to disk."));
    connect(saveAct, SIGNAL(triggered()), this, SLOT(save()));

    saveAsAct = new QAction(QIcon(":/saveas"), 
        tr("Save &As..."), this);
    saveAsAct->setStatusTip(tr("Save the document under a new name."));
    connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));

    saveAllAct = new QAction(tr("Save a&ll"), this);
    saveAllAct->setShortcut(tr("Ctrl+Shift+S"));
    saveAllAct->setStatusTip(tr("Save all open documents to disk."));
    connect(saveAllAct, SIGNAL(triggered()), this, SLOT(doSaveAll()));

    closeAct = new QAction(QIcon(":/close"), tr("&Close"), this);
    closeAct->setStatusTip(tr("Close document."));
    closeAct->setShortcut(tr("Ctrl+W"));
    connect(closeAct, SIGNAL(triggered()), this, SLOT(closeFile()));

    exitAct = new QAction(QIcon(":/exit"), tr("E&xit"), this);
    exitAct->setShortcut(tr("Ctrl+Q"));
    exitAct->setStatusTip(tr("Exit the application"));
    connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));

    cutAct = new QAction(QIcon(":/cut"), tr("Cu&t"), this);
    cutAct->setShortcut(tr("Ctrl+X"));
    cutAct->setStatusTip(tr("Cut the current selection's contents to the "
                            "clipboard."));
    connect(cutAct, SIGNAL(triggered()), this, SLOT(doCut()));

    copyAct = new QAction(QIcon(":/copy"), tr("&Copy"), this);

    copyAct->setStatusTip(tr("Copy the current selection's contents to the "
                             "clipboard."));
    connect(copyAct, SIGNAL(triggered()), this, SLOT(doCopy()));
    
    pasteAct = new QAction(QIcon(":/paste"), tr("&Paste"), this);
    pasteAct->setShortcut(tr("Ctrl+V"));
    pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current "
                              "document."));
    connect(pasteAct, SIGNAL(triggered()), this, SLOT(doPaste()));

    aboutAct = new QAction(tr("&About MUDpad"), this);
    aboutAct->setStatusTip(tr("Show the application's About box."));
    connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));

    aboutQtAct = new QAction(tr("About &Qt"), this);
    aboutQtAct->setStatusTip(tr("Show the Qt library's About box."));
    connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));

    printAct = new QAction(QIcon(":/print"), tr("&Print"), this);
    printAct->setStatusTip(tr("Print current document."));
    connect(printAct, SIGNAL(triggered()), this, SLOT(doPrint()));
    printAct->setShortcut(tr("Ctrl+P"));

    printPDFAct = new QAction(tr("Print to P&DF"), this);
    printPDFAct->setStatusTip(tr("Print the current document to a PDF file."));
    connect(printPDFAct, SIGNAL(triggered()), this, SLOT(doPDFPrint()));

    toggleToolbarsAct = new QAction(tr("Toolbars"), this);
    toggleToolbarsAct->setStatusTip(tr("Show/Hide the Toolbars."));
    toggleToolbarsAct->setCheckable(true);
    toggleToolbarsAct->setShortcut(tr("F4"));
    connect(toggleToolbarsAct, SIGNAL(triggered()), this, 
        SLOT(showHideToolbars()));

    actTabLeft = new QAction(QIcon(":/previous"), "Previous Tab", this);
    actTabLeft->setShortcut(tr("Ctrl+Shift+Tab"));
    connect(actTabLeft, SIGNAL(triggered()), this, SLOT(tabLeft()));
    
    actTabRight = new QAction(QIcon(":/next"), "Next Tab", this);
    actTabRight->setShortcut(tr("Ctrl+Tab"));
    connect(actTabRight, SIGNAL(triggered()), this, SLOT(tabRight()));
    
    actContextHelp = QWhatsThis::createAction(this);
    actContextHelp->setIcon(QIcon(":/context"));
     
    actMudFriendly = new QAction(QIcon(":/mudfriendly"), 
        tr("Enable MUDfriendly"), this);
    actMudFriendly->setStatusTip(tr("Enable MUDfriendly copy/pasting."));
    actMudFriendly->setCheckable(true);
    actMudFriendly->setShortcut(tr("F12"));
    connect(actMudFriendly, SIGNAL(toggled(bool)), this, 
        SLOT(setMudFriendly(bool)));
    
    actViewLines = new QAction(QIcon(":/lines"), tr("Line Numbers"), this);
    actViewLines->setCheckable(true);
    actViewLines->setStatusTip(tr("View line numbers."));
    actViewLines->setToolTip(tr("View line numbers."));
    actViewLines->setShortcut(tr("F11"));
    connect(actViewLines, SIGNAL(toggled(bool)), this, 
        SLOT(setViewLines(bool)));

    actFind = new QAction(QIcon(":/find"), tr("Find..."), this);
    actFind->setShortcut(tr("Ctrl+F"));
    actFind->setStatusTip(tr("Find in text."));
    actFind->setToolTip(tr("Find in text."));
    actFind->setCheckable(true);
    actFind->setChecked(false);
    connect(actFind, SIGNAL(triggered()), this, SLOT(doFind()));

    actFindNext = new QAction(tr("Find next"), this);
    actFindNext->setShortcut(tr("F3"));
    actFindNext->setStatusTip(tr("Find next."));
    actFindNext->setToolTip(tr("Find next."));
    connect(actFindNext, SIGNAL(triggered()), this, SLOT(doFindNext()));

    actFindPrevious = new QAction(tr("Find previous"), this);
    actFindPrevious->setShortcut(tr("Shift+F3"));
    actFindPrevious->setStatusTip("Find previous.");
    actFindNext->setToolTip(actFindPrevious->statusTip());
    connect(actFindPrevious, SIGNAL(triggered()), this, SLOT(doFindPrevious()));


    actFindReplace = new QAction(tr("Find and replace..."), this);
    actFindReplace->setShortcut(tr("Ctrl+H"));
    actFindReplace->setStatusTip(tr("Find and replace text."));
    actFindReplace->setToolTip(tr("Find and replace text."));
    connect(actFindReplace, SIGNAL(triggered()), this, SLOT(doFindReplace()));

    actCloseAll = new QAction(tr("Close all"), this);
    actCloseAll->setStatusTip(tr("Close all open documents."));
    actCloseAll->setToolTip(tr("Close all open documents."));
    actCloseAll->setShortcut(tr("Ctrl+Shift+W"));
    connect(actCloseAll, SIGNAL(triggered()), this, SLOT(doCloseAll()));
    
    actReload = new QAction(QIcon(":/reload"), tr("&Reload"), this);
    actReload->setStatusTip(tr("Reload current document."));
    actReload->setToolTip(actReload->statusTip());
    actReload->setShortcut(tr("F5"));
    connect(actReload, SIGNAL(triggered()), this, SLOT(doReload()));

    actUndo = new QAction(QIcon(":/undo"), tr("&Undo"), this);
    actUndo->setStatusTip(tr("Undo last edit."));
    actUndo->setToolTip(actUndo->statusTip());
    actUndo->setShortcut(tr("Ctrl+Z"));
    connect(actUndo, SIGNAL(triggered()), this, SLOT(doUndo()));

    actRedo = new QAction(QIcon(":/redo"), tr("&Redo"), this);
    actRedo->setStatusTip(tr("Redo last edit."));
    actRedo->setToolTip(actRedo->statusTip());
    actRedo->setShortcut(tr("Shift+Ctrl+Z"));
    connect(actRedo, SIGNAL(triggered()), this, SLOT(doRedo()));
}

void MPadWin::doReload(GNumberedEdit* v) {
    if(!v) v = curTab();
    if(docs[v].full_file_name.isNull()) return ;
    m_opening = true;
    if(!loadFile(v, docs[v].full_file_name)) {
        QMessageBox::critical(this, "MUDpad",
            QString("MUDpad was unable to read the file "
            "<strong>\'%1\'</strong>.").arg(docs[v].full_file_name)); 
        return ;
    }
    docs[v].last_modified = QFileInfo(docs[v].full_file_name).lastModified();
    m_opening = false;
}

void MPadWin::doFindReplace() {
    if(replace != 0) {
        replace->show();
        replace->activateWindow();
    } else {
        replace = new DlgFindReplace(this,
                        Qt::MSWindowsFixedSizeDialogHint |
                        Qt::WindowTitleHint |
                        Qt::WindowStaysOnTopHint |
                        Qt::Dialog);

        replace->chkCase->setChecked(m_case);
        replace->txtFind->setText(m_search);
        replace->chkWord->setChecked(m_word);
        replace->txtFind->selectAll();
    
        replace->txtFind->setFocus();
        connect(replace->cmdFindNext, SIGNAL(clicked()), this, 
            SLOT(doFindNext()));
        connect(replace->cmdReplace, SIGNAL(clicked()), this, 
            SLOT(doReplace()));
        connect(replace->cmdReplaceAll, SIGNAL(clicked()), this, 
            SLOT(doReplaceAll()));
        replace->show();
    }
}

void MPadWin::doReplace() {
    if(!replace) return ;
    this->setFocus();
    QTextCursor cursor = curDoc()->textCursor();
    if(cursor.hasSelection()) {
        cursor.insertText(replace->txtReplace->text());
    }
}

void MPadWin::doReplaceAll() {
    int i = 0;
    m_search = replace->txtFind->text();
    m_case = replace->chkCase->isChecked();
    while(doFindNext()) {
        i++;
        doReplace();
    }
    statusBar()->showMessage(tr("%1 %2 of '%3' replaced with '%4'.")
            .arg(i)
            .arg(i == 1 ? tr("instance") : tr("instances"))
            .arg(m_search)
            .arg(replace->txtReplace->text()), 30000);
    delete(replace);
    replace = 0;
}

bool MPadWin::doFindNext() {
    bool found;
    if(!replace && m_search.isEmpty()) { doFind(); return false; }
    QTextDocument::FindFlags flags;
    if(m_case) flags |= QTextDocument::FindCaseSensitively;
    if(m_word) flags |= QTextDocument::FindWholeWords;
    found = curDoc()->find(m_search, flags);
    if(!found) {
        statusBar()->showMessage(tr("No further matches found for '%1'.")
            .arg(m_search),30000);
    }
    this->activateWindow();
    return found;
}

bool MPadWin::doFindPrevious() {
    bool found;

    if(!replace && m_search.isEmpty()) { doFind(); return false; }
    QTextDocument::FindFlags flags;
    flags |= QTextDocument::FindBackward;
    if(m_case) flags |= QTextDocument::FindCaseSensitively;
    if(m_word) flags |= QTextDocument::FindWholeWords;
    found = curDoc()->find(m_search, flags);
    if(!found) {
        statusBar()->showMessage(tr("No matches found for '%1'.").
            arg(m_search),30000);
    }
    this->activateWindow();
    return found;
}

void MPadWin::doFind() {
    fbar->load();
    actFind->setChecked(fbar->isVisible());
    return ;
    bool found = false;
    DlgFind find(this,
                    Qt::MSWindowsFixedSizeDialogHint |
                    Qt::WindowTitleHint |
                    Qt::WindowStaysOnTopHint |
                    Qt::Dialog);    
    find.rdoUp->setChecked(m_back);
    find.rdoDown->setChecked(!m_back);
    find.chkCase->setChecked(m_case);
    find.chkWord->setChecked(m_word);
    find.txtFind->setText(m_search);

    find.txtFind->setFocus();
    find.txtFind->selectAll();
    
    if (find.exec() == QDialog::Accepted) {
        QTextDocument::FindFlags flags;
        if(m_back = find.rdoUp->isChecked())
            flags |= QTextDocument::FindBackward;
        if(m_case = find.chkCase->isChecked()) 
            flags |= QTextDocument::FindCaseSensitively;
        if(m_word = find.chkWord->isChecked()) 
            flags |= QTextDocument::FindWholeWords;
        found = curDoc()->find(m_search = find.txtFind->text(), flags);
    } else return ;
    if(!found) {
        statusBar()->showMessage(tr("No further matches found for '%1'.")
            .arg(m_search),30000);
    }
}

void MPadWin::doFindB(QString s, bool forward, bool matchcase) {
    m_search = s;
    QTextCursor c = curDoc()->textCursor();
    c.setPosition(0);
    curDoc()->setTextCursor(c);
    c.clearSelection();
    if(s.isEmpty()) {
        emit(textFound(true));
        return ;
    }
    
    QTextDocument::FindFlags flags;
    if(m_back = !forward) flags |= QTextDocument::FindBackward;
    if(m_case = matchcase) flags |= QTextDocument::FindCaseSensitively;
    bool found;
    found = curDoc()->find(m_search = s, flags);
    emit (textFound(found));
}

void MPadWin::setViewLines(bool yn) {
    m_lines = yn;
    updateDisplays();
    writeSettings();
}

bool MPadWin::viewLines() const {
    return m_lines;
}

void MPadWin::tabRight() {
    int t = tabs->currentIndex();
    if(t == tabs->count()-1) tabs->setCurrentIndex(0);
    else tabs->setCurrentIndex(t+1);
}

void MPadWin::tabLeft() {
    int t = tabs->currentIndex();
    if(t == 0) tabs->setCurrentIndex(tabs->count()-1);
    else tabs->setCurrentIndex(t-1);
}

void MPadWin::createMenus() {
    fileMenu = menuBar()->addMenu(tr("&File"));
    fileMenu->addAction(newAct);
    fileMenu->addAction(openAct);
    fileMenu->addAction(actReload);
    fileMenu->addAction(saveAct);
    fileMenu->addAction(saveAsAct);
    fileMenu->addAction(saveAllAct);
    fileMenu->addAction(closeAct);
    fileMenu->addAction(actCloseAll);
    fileMenu->addSeparator();
    fileMenu->addAction(printAct);
    fileMenu->addAction(printPDFAct);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAct);

    editMenu = menuBar()->addMenu(tr("&Edit"));
    editMenu->addAction(cutAct);
    editMenu->addAction(copyAct);
    editMenu->addAction(pasteAct);
    editMenu->addSeparator();
    editMenu->addAction(actUndo);
    editMenu->addAction(actRedo);
    editMenu->addSeparator();
    editMenu->addAction(actFind);
    editMenu->addAction(actFindNext);
    editMenu->addAction(actFindPrevious);
    editMenu->addAction(actFindReplace);
    editMenu->addSeparator();
    editMenu->addAction(actMudFriendly);

    viewMenu = menuBar()->addMenu(tr("&View"));
    viewMenu->addAction(toggleToolbarsAct);
    viewMenu->addSeparator();
    viewMenu->addAction(actTabRight);
    viewMenu->addAction(actTabLeft);
    viewMenu->addSeparator();
    viewMenu->addAction(actViewLines);

    helpMenu = menuBar()->addMenu(tr("&Help"));
    helpMenu->addAction(aboutAct);
    helpMenu->addAction(aboutQtAct); 
}

void MPadWin::createToolBars() {
    mainToolBar = addToolBar(tr("Main"));

    mainToolBar->addAction(newAct);
    mainToolBar->addAction(openAct);
    mainToolBar->addAction(actReload);
    mainToolBar->addAction(saveAct);
    mainToolBar->addAction(closeAct);
    mainToolBar->addAction(printAct);
    mainToolBar->addSeparator();
    mainToolBar->addAction(actViewLines);
    mainToolBar->addAction(actTabLeft);
    mainToolBar->addAction(actTabRight);
    mainToolBar->addSeparator();
    mainToolBar->addAction(actUndo);
    mainToolBar->addAction(actRedo);
    mainToolBar->addSeparator();
    mainToolBar->addAction(actFind);
    mainToolBar->addAction(copyAct);
    mainToolBar->addAction(cutAct);
    mainToolBar->addAction(pasteAct);
    mainToolBar->addSeparator();
    mainToolBar->addAction(actContextHelp);
    
    addToolBarBreak();

    fontToolBar = addToolBar(tr("Font"));
    fonts = new QFontComboBox(fontToolBar);
    fonts->setFontFilters(QFontComboBox::MonospacedFonts);
    fonts->setFocusPolicy(Qt::NoFocus);
    fontSize = new QSpinBox(fontToolBar);
    fontSize->setSuffix(" pt");
    fontSize->setMaximum(20);
    fontSize->setMinimum(9);
    fontSize->setFocusPolicy(Qt::NoFocus);
    fontToolBar->addWidget(fonts);
    fontToolBar->addWidget(fontSize);
    
    addToolBarBreak();
    
    mudToolBar = addToolBar(tr("MUD"));
    mudToolBar->addAction(actMudFriendly);
    mudToolBar->addWidget(new QLabel(tr("Wrap Column")));
    edRight= new QSpinBox(mudToolBar);
    edRight->setMinimum(50);
    edRight->setMaximum(79);
    mudToolBar->addWidget(edRight);
    mudToolBar->addWidget(new QLabel(tr("Left Indent")));
    edLeft = new QSpinBox(mudToolBar);
    edLeft->setMinimum(0);
    edLeft->setMaximum(10);
    mudToolBar->addWidget(edLeft);
    mudToolBar->addSeparator();
    chkPreserveDot = new QCheckBox(mudToolBar);
    chkPreserveDot->setText(tr("No indent on first/last lines"));
    mudToolBar->addWidget(chkPreserveDot);
    
    connect(edLeft, SIGNAL(valueChanged(int)), this,
        SLOT(updateLeft(int)));
    connect(edRight, SIGNAL(valueChanged(int)), this,
        SLOT(updateRight(int)));
    connect(chkPreserveDot, SIGNAL(stateChanged(int)), this,
        SLOT(updateDot(int)));

    edLeft->setFocusPolicy(Qt::NoFocus);
    edRight->setFocusPolicy(Qt::NoFocus);
    chkPreserveDot->setFocusPolicy(Qt::NoFocus);
    
    mudToolBar->setIconSize(QSize(22, 22));
    //mudToolBar->setMovable(false);
    mainToolBar->setIconSize(QSize(22, 22));
    //mainToolBar->setMovable(false);
    //fontToolBar->setMovable(false);
    
}

void MPadWin::updateDot(int i) {
    switch(i) {
        case 0 : 
            m_dot = false;
            break;
        case 2 : 
            m_dot = true;
            break;
        default :
            m_dot = false;
            break;
    }
    updateDisplays();
    writeSettings();
}

void MPadWin::updateLeft(int i) {
    m_indent = i;
    updateDisplays();
    writeSettings();
}

void MPadWin::updateRight(int i) {
    m_wrap = i;
    updateDisplays();
    writeSettings();
}

void MPadWin::createStatusBar() {
    statusBar()->showMessage(tr("Ready"));
}

void MPadWin::readSettings() {
    QSettings m_settings("Ellenia Group", "MUDpad");
    m_pos = m_settings.value("pos", QPoint(200, 200)).toPoint();
    m_size = m_settings.value("size", QSize(400, 400)).toSize();
#ifndef Q_OS_X11
    m_maximized = m_settings.value("maximized", false).toBool();
#endif
    m_font.fromString(m_settings.value("font", "Bitstream Vera Sans Mono,10")
        .toString());
    fonts->setCurrentFont(m_font);
    fontSize->setValue(m_font.pointSize());
    m_toolbars = m_settings.value("toolbars", false).toBool();
    QDir dir(".");
#ifdef Q_OS_WIN32
    QString def_dir = QString("%1/%2").arg(dir.homePath())
        .arg(tr("My Documents"));
#else
    QString def_dir = QString("%1").arg(dir.homePath());
#endif
    m_lastpath = m_settings.value("lastpath", def_dir).toString();
    m_mudfriendly = m_settings.value("mudfriendly", false).toBool();
    m_indent = m_settings.value("indent", 0).toInt();
    m_wrap = m_settings.value("wrap", 79).toInt();
    m_dot = m_settings.value("dot", false).toBool();
    m_lines = m_settings.value("lines", false).toBool();
}

void MPadWin::writeSettings() {
    if(m_initializing) return ;
    QSettings m_settings("Ellenia Group", "MUDpad");
    m_settings.setValue("pos", m_pos);
    m_settings.setValue("size", m_size);
#ifndef Q_OS_X11
    m_settings.setValue("maximized", isMaximized());
#endif
    m_settings.setValue("toolbars", m_toolbars);
    m_settings.setValue("font", m_font.toString());
    m_settings.setValue("lastpath", m_lastpath);
    m_settings.setValue("mudfriendly", m_mudfriendly);
    m_settings.setValue("wrap", m_wrap);
    m_settings.setValue("indent", m_indent);
    m_settings.setValue("dot", m_dot);
    m_settings.setValue("lines", m_lines);
}


bool MPadWin::closeFile(GNumberedEdit *v)  {
    if(!v) v = curTab();
    if(v->edit()->dirty()) {
        int ret = QMessageBox::warning(this, 
            QString("MUDpad - %1").arg(title(v)),
                tr("The document has been modified.\n"
                "Do you want to save your changes?"),
                QMessageBox::Yes | QMessageBox::Default,
                QMessageBox::No, QMessageBox::Cancel | 
                QMessageBox::Escape);
        if (ret == QMessageBox::Yes) saveDocument(curTab());
        else if (ret == QMessageBox::Cancel) return false;
    }
    int i = tabs->indexOf(v);
    tabs->removeTab(i);
    docs.remove(v);
    delete v;
    if(!m_closing) {
        if(!tabs->count()) newFile();
    }
    return true;
}

void MPadWin::showHideToolbars() {
    if(!m_initializing) m_toolbars = toggleToolbarsAct->isChecked();
    mainToolBar->setVisible(m_toolbars);
    fontToolBar->setVisible(m_toolbars);
    mudToolBar->setVisible(m_toolbars);
    writeSettings();
}

void MPadWin::doPaste() {
    curDoc()->paste();
}

void MPadWin::doCut() {
    curDoc()->cut();
}

void MPadWin::doCopy() {
    curDoc()->copy();
}

void MPadWin::saveAs() {
    saveDocument(curTab(), true);
}

void MPadWin::fontUpdate(QFont font) {
        font.setPointSize(m_font.pointSize());
        m_font = font;
        updateDisplays();
        writeSettings();
}

void MPadWin::fontUpdateSize(int sz) {
    m_font.setPointSize(sz);
    updateDisplays();
    writeSettings();
}

void MPadWin::updateDisplay() {
    updateDisplay(curTab());
}

void MPadWin::updateDisplay(GNumberedEdit *doc) {
    doc->edit()->setFont(m_font);
    doc->edit()->setTextIndent(m_indent);
    doc->edit()->setWrapColumn(m_wrap);
    doc->edit()->setMudFriendly(m_mudfriendly);
    doc->edit()->setCheckForDot(m_dot);
    doc->setViewLineNumbers(m_lines);
}

void MPadWin::updateDisplays() {
    if(m_mudfriendly) {
        if(m_indent < 1) chkPreserveDot->setEnabled(false);
        else chkPreserveDot->setEnabled(true);
    }
    QVectorIterator<GNumberedEdit*> d(docs.keys().toVector());
    
    while(d.hasNext()) {
        GNumberedEdit *doc = d.next();
        updateDisplay(doc);
    }
    curDoc()->setFocus();
}

void MPadWin::doPrint() {
    #ifndef QT_NO_PRINTER
        QPrinter *printer = new QPrinter(QPrinter::HighResolution);
        printer->setFullPage(true);
        QPrintDialog *printDialog = new QPrintDialog(printer, curDoc());
        if (printDialog->exec() == QDialog::Accepted) {
           curDoc()->document()->print(printer);
        }
    #endif
}

void MPadWin::doPDFPrint() {
    #ifndef QT_NO_PRINTER
        QString fileName = QFileDialog::getSaveFileName(curDoc(), 
            tr("Export to PDF"), 
            QString(), 
            tr("Portable Document Format (*.pdf)"));
        if (fileName.isEmpty())
            return;
        if (!fileName.endsWith(".pdf", Qt::CaseInsensitive)) {
            fileName.append(".pdf");
        }
        QPrinter printer(QPrinter::HighResolution);
        printer.setOutputFormat(QPrinter::PdfFormat);
        printer.setOutputFileName(fileName);
        curTab()->doc()->print(&printer);
    #endif
}

void MPadWin::updateStatus(GNumberedEdit *v) {
    if(!v) v = qobject_cast<GNumberedEdit*>(sender());
    if(m_opening) {
        int i = tabs->indexOf(v);
        tabs->setTabText(i, title(v));
        tabs->setTabIcon(i, QIcon(":/file_icon"));
        docs[v].new_data = false;
        switchDocument(i);
        return ;
    }
    if(!docs[v].new_data) {
        int i = tabs->indexOf(v);
        tabs->setTabText(i, QString("%1%2")
                            .arg(v->edit()->dirty() ? "*" : "")
                            .arg(title(v)));
        tabs->setTabIcon(i, v->edit()->dirty() ? QIcon(":/file_icon_changed")
                                       : QIcon(":/file_icon"));
        switchDocument(i);
    } else docs[v].new_data = false;
}

void MPadWin::switchDocument(int i) {
    GNumberedEdit *v = qobject_cast<GNumberedEdit*>(tabs->widget(i));
    QString t = docs[v].file_name.isEmpty() ? title(v) : fileName(v);
#ifdef Q_OS_WIN32
    t = QDir::convertSeparators(t);
#endif
    setWindowTitle(QString("%2%1 - MUDpad")
        .arg(t)
        .arg(!m_opening && v->edit()->dirty() ? "*" : ""));
    v->edit()->setFocus();
    enableCopy(docs[v].copy_available);
    enableUndo(docs[v].undo_available);
    enableRedo(docs[v].redo_available);
}


QString MPadWin::lastPath() const {
    return m_lastpath;
}

void MPadWin::setLastPath(QString lastPath) {
    m_lastpath = lastPath;
    writeSettings();
}

void MPadWin::doSaveAll() {
    QVectorIterator<GNumberedEdit*> d(docs.keys().toVector());
    
    while(d.hasNext())
        saveDocument(d.next());
}

QString MPadWin::fileName(GNumberedEdit *v) {
    if(docs[v].file_name.isEmpty()) return QString();
    return QString("%1/%2")
        .arg(docs[v].path)
        .arg(docs[v].file_name);
}

void MPadWin::saveDocument(GNumberedEdit *v, bool promptFileName) {
    QString f;

    f = promptFileName ? newFileName() :
        fileName(v).isEmpty() ? newFileName() : fileName(v);
    if (f.isEmpty()) return ;
    if(f.lastIndexOf(".") == -1) {
        f.append(".mud");
    }
    saveDocument(v, f);
    return ;
}

void MPadWin::saveDocument(GNumberedEdit *v, QString fileName) {
    QFile file(fileName);
    
    if (!file.open(QFile::WriteOnly | QFile::Text)) {
        QMessageBox::warning(this, tr("MUDpad"),
                             tr("Cannot write file %1:\n%2.")
                             .arg(fileName)
                             .arg(file.errorString()));
        return ;
    }
    QTextStream out(&file);
    QApplication::setOverrideCursor(Qt::WaitCursor);
    out << v->edit()->text();
    file.flush();
    file.close();
    QApplication::restoreOverrideCursor();

    v->doc()->setModified(false);
    docs[v].new_data = false;
    docs[v].full_file_name = fileName;
    docs[v].path = strippedPath(docs[v].full_file_name);
    docs[v].file_name = strippedName(docs[v].full_file_name);
    docs[v].last_modified = QFileInfo(fileName).lastModified();
    setLastPath(docs[v].path);
    updateStatus(v);
    emit(dataSaved(v));
    return ;
}

QString MPadWin::newFileName() {
    QString p;
    GNumberedEdit *v = curTab();
    if(!docs[v].path.isEmpty()) p = docs[v].path;
    else p = lastPath();
    return QFileDialog::getSaveFileName(curDoc(), "Save File As", p, 
        FILE_ASSOC);
}

void MPadWin::enableCopy(bool y) {
    docs[curTab()].copy_available = y;
    copyAct->setEnabled(y);
    cutAct->setEnabled(y);
}

void MPadWin::enableUndo(bool y) {
    docs[curTab()].undo_available = y;
    actUndo->setEnabled(y);
}

void MPadWin::enableRedo(bool y) {
    docs[curTab()].redo_available = y;
    actRedo->setEnabled(y);
}

void 
MPadWin::makeWhatsThis(QAction *act, QString icon, QString t, QString text) {    
    if(!icon.isNull()) {
        text = QString("<p><img src=\"%1\" /><br /><strong>%2</strong>"
            "<hr /></p><p>%3</p>")
            .arg(icon)
            .arg(t)
            .arg(text);
    } else {
        text = QString("<p><strong>%1</strong><hr /></p><p>%2</p>")
            .arg(t)
            .arg(text);
    }
    act->setWhatsThis(text);
}
void
MPadWin::makeWhatsThis(QWidget *act, QString icon, QString t, QString text) {
    
    if(!icon.isNull()) {
        text = QString("<p><img src=\"%1\" /><br /><strong>%2</strong>"
            "<hr /></p><p>%3</p>")
            .arg(icon)
            .arg(t)
            .arg(text);
    } else {
        text = QString("<p><strong>%1</strong><hr /></p><p>%2</p>")
            .arg(t)
            .arg(text);
    }
    act->setWhatsThis(text);
}

void MPadWin::createWhatsThis() {
    makeWhatsThis(newAct, ":/new", "File | New", 
    "Use this option to open a new tab with a new, blank file.");
    makeWhatsThis(newTabAct, ":/newtab", "File | New",
    "Use this option to open a new tab with a new, blank file.");
    makeWhatsThis(removeTabAct, ":/deltab", "File | Close",
    "Close the current tab. If the contents have changed since they were "
    "last saved, you will be prompted to save the data.");
    makeWhatsThis(closeAct, ":/close", "File | Close",
    "Close the current tab. If the contents have changed since they were "
    "last saved, you will be prompted to save the data.");
    makeWhatsThis(openAct, ":/open", "File | Open",
    "Open a document for editing within MUDpad. You may open any sort of "
    "file, but MUDpad has been designed and optimised for text files.");
    makeWhatsThis(saveAct, ":/save", "File | Save",
    "If you have not already saved your file, it will act as if <strong>File | "
    "Save as...</strong>. However, once saved, <strong>Save</strong> will save "
    "your file to disc.");
    makeWhatsThis(saveAsAct, ":/saveas", "File | Save as...",
    "This will prompt you for a file name under which to save your current "
    "document.");
    makeWhatsThis(saveAllAct, QString(), "File | Save all",
    "Executing this action will cause all of your files to save. Any files "
    "which have never been saved will prompt for filenames. It is best to use "
    "this function when all have been saved at least once, as when there are "
    "more than one previously unsaved documents open, there is no way to "
    "easily determine which file is which when being prompted for a file "
    "name. It is recommended to cancel this operation at that time and save "
    "each previously unsaved file individually before using the <strong>Save "
    "all</strong> functionality.");
    makeWhatsThis(exitAct, ":/exit", "File | Exit",
    "This will exit out of MUDpad. If there are any unsaved documents, they "
    "will each present you with an opportunity to choose file names.");
    makeWhatsThis(cutAct, ":/cut", "Edit | Cut",
    "Use this to cut existing text out of a document. Data thus cut is placed "
    "into the clipboard.<br /><br /><em>* MUDfriendly settings do not impact "
    "cutting text.</em>");
    makeWhatsThis(copyAct, ":/copy", "Edit | Copy", 
    "Use this to copy existing document data into the clipboard.</p>"
    "<p>If the MUDfriendly option is set, copied text will be refactored to "
    "conform to the 79 character width limit that is imposed upon the editors "
    "in the game.</p>");
    makeWhatsThis(pasteAct, ":/paste", "Edit | Paste",
    "Paste text from the clipboard at the current cursor location in the "
    "active document.</p><p>In MUDfriendly mode, the tab character is quietly "
    "replaced with spaces when pasting.");
    makeWhatsThis(aboutAct, QString(), "Help | About",
    "This will show you the About data for MUDpad, including the version and "
    "license information.");
    makeWhatsThis(aboutQtAct, QString(), "Help | About Qt",
    "This will show you the About data for Qt.");
    makeWhatsThis(printAct, ":/print", "File | Print",
    "Print the current document. Doing so will prompt you to which printer "
    "you would like to send your document.");
    makeWhatsThis(printPDFAct, QString(), "File | Print do PDF",
    "Use this for when you really want to save your file as a PDF. I'm not "
    "sure why I put this in, other than to just be neat.");
    makeWhatsThis(toggleToolbarsAct, QString(), "View | Toolbars",
    "Toggles whether you see the toolbars within MUDpad.");
    makeWhatsThis(actTabLeft, ":/previous", "View | Previous Tab",
    "Cycle left-ward through the open tabs/documents. This will cycle around "
    "to the last one when pressed upon the first. There is no result when "
    "there is only one tab open.");
    makeWhatsThis(actTabRight, ":/next", "View | Next Tab",
    "Cycle right-ward through the open tabs/documents. This will cycle around "
    "to the first one when pressed upon the last. There is no result when "
    "there is only one tab open.");
    makeWhatsThis(actContextHelp, ":/context", "Mow Lawn",
    "Pressing this icon will enter you into a lottery. The winner gets a free "
    "lawn mowing. There are 0 in 100000000 chances of winning. Chance of "
    "winning have been artificially set. You must answer a skill-testing "
    "question in order to redeem your prize.");  
    makeWhatsThis(actMudFriendly, ":/mudfriendly", "Edit | Enable MUDfriendly",
    "Enabling this option will offer you the option of setting the margins "
    "of copied text.</p><p>You must have the toolbars shown to edit "
    "the values, however.");
    makeWhatsThis(edRight, QString(), "Wrap Column",
    "When copying, MUDpad will automatically convert the text so that it "
    "conforms to the limitations of the in-game editors. This is the column "
    "at which your text will be automatically wrapped in the clipboard.");
    makeWhatsThis(edLeft, QString(), "Left Indent",
    "If you like to have your text indented automatically by a few spaces, "
    "select a value here. Please keep in mind that indents are supposed to be "
    "small number, usually between 1 and 5 characters. If you make it too "
    "large it begins to look ridiculous. When copying text, this comprises "
    "into the wrapping in the Right Margin.");
    makeWhatsThis(chkPreserveDot, QString(), "No indent on first/last lines",
    "Setting this options means that when you copy information out of "
    "MUDpad, it will not indent the first and last lines. This is useful "
    "for those who desire to put the edit command (post, mail, describe, "
    "decorate, etc) plus the final \".\" to exit all in the same edit.");
    makeWhatsThis(actFind, ":/find", "Edit | Find...",
    "Use this feature to locate text within your document which matches "
    "criteria of your choosing.");
    makeWhatsThis(actFindNext, QString(), "Edit | Find next",
    "MUDpad remembers the last text for which you searched. To merely continue "
    "your search throughout your document without re-specifying your search "
    "terms, simply press F3 or click Edit | Find next");
    makeWhatsThis(actFindPrevious, QString(), "Edit | Find previous",
    "MUDpad remembers the last text for which you searched. To merely continue "
    "your search throughout your document without re-specifying your search "
    "terms, simply press Shfit+F3 or click Edit | Find previous");
    makeWhatsThis(actFindReplace, QString(), "Edit | Find and replace...",
    "MUDpad allows you to replace user-specified text with new text. Simply "
    "do a Find and replace to perform this action.");    
    makeWhatsThis(actViewLines, ":/lines", "View | Line numbers",
    "Show line numbers in the left-most gutter of your documents. If text "
    "spans more than a line and wraps, this counts as 1 line.");
    makeWhatsThis(actReload, ":/reload", "File | Reload",
    "Reload the current document from disk. All changes since the last save "
    "will be lost.");
    makeWhatsThis(actUndo, ":/undo", "Edit | Undo",
    "Undo your last edit.");
    makeWhatsThis(actRedo, ":/redo", "Edit | Redo",
    "If you have previously performed any undo's and there are any left in "
    "memory, clicking this will restore your document's state before your last "
    "undo.");
}

void MPadWin::setMudFriendly(bool yn) {
    m_mudfriendly = yn;
    actMudFriendly->setChecked(yn);
    edLeft->setEnabled(yn);
    edRight->setEnabled(yn);
    chkPreserveDot->setEnabled(yn);
    updateDisplays();
    writeSettings();
}

void MPadWin::resizeEvent ( QResizeEvent * event ) {
    if(!isMaximized()) {
        m_size = size();
        event->accept();
        return ;
    }
    QWidget::resizeEvent(event);
}

void MPadWin::moveEvent (QMoveEvent *e) {
    QWidget::moveEvent(e);
    if(!isMaximized()) {
        m_pos = pos();
    }
    e->accept();
}

QString MPadWin::strippedName(const QString fullFileName) {
    return QFileInfo(fullFileName).fileName();
}

QString MPadWin::strippedPath(const QString fullFileName) {
    QFileInfo file(fullFileName);
    QString p = file.absolutePath();
    return QFileInfo(fullFileName).absolutePath();
}

void MPadWin::doUndo() {
    curDoc()->document()->undo();
}

void MPadWin::doRedo() {
    curDoc()->document()->redo();
}

void MPadWin::findBarHidden(bool y) {
    actFind->setChecked(y);
    if(y) {
        curDoc()->setFocus();
    }
}

void MPadWin::slotRequestFindPrevious(bool y) {
    m_case = y;
    doFindPrevious();
}

void MPadWin::slotRequestFindNext(bool y) {
    m_case = y;
    doFindNext();
}
